﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using ProjectBase.Core;

using Survey.Common;
using Survey.Common.Validation;

namespace Survey.Business
{
    public class EnumerableRule<TItem, TValue> : RuleBase, IValidationRule<TItem>
        where TItem : class
    {
        #region members
        private readonly Func<TItem, IEnumerable<TValue>> _compiledExpression;
        string _propertyName;
        #endregion members

        #region Constructor
        public EnumerableRule(Expression<Func<TItem, IEnumerable<TValue>>> expression)
        {
            Contract.Requires(expression.Is());

            var body = expression.Body as MemberExpression;
            if (body.IsNull())
            {
                throw new NotSupportedException(
                    "Provided 'Expression<Func<TITem, IEnumerable<TValue>>>' must be of a 'ExpressionType.MemberAccess' (EnumerableRule). ");
            }

            _propertyName = body.Member.Name;
            _compiledExpression = expression.Compile();
        }
        #endregion Constructor

        #region Validate

        public virtual ValidationResult Validate(TItem item, out ValidationMessage message)
        {
            message = null;

            // item cannot be null
            if (item.IsNull())
            {
                message = new ValidationMessage(Str.Messages.NullInsteadOfEntityProvided1)
                {
                    EntityName,
                };
                return ValidationResult.Error;
            }

            var result = CompiledExpression.Invoke(item);

            // IEnumerable is null or empty
            if (result.IsEmpty())
            {
                message = new ValidationMessage(Str.Messages.EmptyCollection1)
                {
                    PropertyName.GetLocalized(EntityName),
                };
                return ValidationResult.Error;
            }

            return ValidationResult.IsValid;
        }

        #endregion Validate

        #region properties
        protected virtual Func<TItem, IEnumerable<TValue>> CompiledExpression { get { return _compiledExpression; } }
        protected virtual string PropertyName
        {
            get { return _propertyName; }
            set { _propertyName = value; }
        }
        protected virtual string EntityName { get { return typeof(TItem).Name; } }
        #endregion properties
    }
}